package com.dong.common.io;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

public class NIOServerTest {
    public static void main(String[] args) throws IOException {
        //创建个一个selector多路复用器
        Selector selector = Selector.open();

        //创建一个ServerSocketChannel，相当于开启一个服务
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //设置为非阻塞模式,王八的屁股 - 龟腚(规定)
        serverSocketChannel.configureBlocking(false);
         // 绑定8080端口
        serverSocketChannel.bind(new InetSocketAddress(8080));

        //将serverSocketChannel注册到多路复用器selector上,注册accept事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println("server is started!");

        //获取就绪的Channel
        Set<SelectionKey> selectionKeys = selector.selectedKeys();

        while(true){
            //第一阶段 阻塞在select上
            selector.select();
            //遍历待处理的客户端连接请求
            Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
            while (selectionKeyIterator.hasNext()) {
                SelectionKey selectionKey = selectionKeyIterator.next();

                //处理客户端请求
                if (selectionKey.isAcceptable()) {
                    //若接受的事件是“接收就绪” 操作,就获取客户端连接
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println("接受到新的连接："+socketChannel.getRemoteAddress());
                    // 切换为非阻塞模式
                    socketChannel.configureBlocking(false);
                    //将这个SocketChannel注册到Selector上，注册读事件
                    socketChannel.register(selector,SelectionKey.OP_READ);
                }else if (selectionKey.isReadable()){
                    // 获取该选择器上的“读就绪”状态的通道
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    // 读取数据
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    int length = 0;
                    while ((length = socketChannel.read(byteBuffer)) != -1)
                    {
                        byteBuffer.flip();
                        System.out.println(new String(byteBuffer.array(), 0, length));
                        byteBuffer.clear();
                    }
                    socketChannel.close();
                }
                selectionKeyIterator.remove();
            }
        }
    }
}
